/**
  SUNNY Project, Anyang Normal University, IMP-CAS
	\class TAMBSD
	\brief Slater determinant (SD) class for many-body problems. Each SD represents
	a configuration of the nucleons in the single-particle state.
	\author SUN Yazhou
	\since 2020/01/31
	\date Last modified: 2021/02/10 by Sun Yazhou
	\copyright 2020-2023 SUN Yazhou
	\copyright SUNNY project, Anyang Normal University, IMP-CAS
*/

#include <iostream>
#include <iomanip>
#include <cmath>
#include "TAMBSD.h"
#include "TAException.h"
#include "TASPState.h"
#include "TASPStateManager.h"

using std::cout;
using std::endl;
using std::setw;

TAMBSD::TAMBSD(ull bit) : fBit(bit){
} // end the constructor

TAMBSD::~TAMBSD(){} // end the destructor


void TAMBSD::GetSPStateArr(int *p) const{
  fBit.GetSPStateArr(p);
} // end member function GetSPStateArr

int TAMBSD::Get2M() const{
  int total2M = 0;
  for(int i = fBit.count(); i--;) total2M += (*this)[i]->Get2Mj();
  return total2M;
} // end member function Get2M
int TAMBSD::M() const{
  int m = 0;
  for(int i = fBit.count(); i--;) m += (*this)[i]->mj();
  return m;
} // end member function M

// parity
bool TAMBSD::Parity() const{
  int l = 0;
  for(int i = fBit.count(); i--;) l += (*this)[i]->l();
  return l & 1 ? false : true;
} // end member function Parity

// \retval '+' for + and '-' for -
char TAMBSD::ParityChar() const{
  if(pi()) return '+';
  return '-';
} // end member functoin ParityChar


int TAMBSD::Get2T() const{
  int total2T = 0;
  for(int i = fBit.count(); i--;) total2T += (*this)[i]->Get2Tz();
  return total2T;
} // end member function Get2T
int TAMBSD::T() const{
  int t = 0;
  for(int i = fBit.count(); i--;) t += (*this)[i]->tz();
  return t;
} // end member functiion Get2T

double TAMBSD::GetEnergy() const{
  double e = 0.;
  for(int i = fBit.count(); i--;) e += (*this)[i]->e();
  return e;
} // end member function GetEnergy

// note that this method works only if piared states are next to each other,
// and SPStates are ordered in ManyBodySD
bool TAMBSD::IsPaired() const{
  // obtain the sp state array
  const int n = fBit.count();
  // XXX VLA: varialble length array; FIXME //
  int p[n]; for(auto &t : p) t = 0;
  GetSPStateArr(p);

  // identify broken pairs //
  int i = 0, nSingle = 0;
  while(i < n){
    // p[i] even and p[i+1]=p[i]+1
    if(i < n-1 && !(p[i]%2) && p[i+1]-p[i] == 1) i += 2;
    else{ nSingle++; i++; }
  } // end while
  if(nSingle <= 1) return true;
  return false;
} // end member function IsPaired

/// \retval sp state of the i-th particle
const TASPState *TAMBSD::operator[](int i) const{
  static const auto &spv = TASPStateManager::Instance()->GetSPStateVec();
  const int n = spv.size();
  int np = -1, j;
  if(i < 0 || i >= n) TAException::Error("TAMBSD",
    "operator[%d]: Subscript of the requested element is out of range.", i);
  // obtain the sp state array /
  for(j = 0; j < n; j++){
    if(fBit.test(j)) np++;
    if(np == i) break;
  }
  const TASPState *sp = spv[j];
  if(!sp) TAException::Error("TAMBSD",
    "operator[%d]: Required pointer is null.", i);
  return sp;
} // end member function operator[]

// self-display
void TAMBSD::Print() const{
  cout << setw(3) << ParityChar();
  cout << setw(3) << Get2M() << setw(3) << Get2T() << setw(5) << GetEnergy();
  cout << setw(8) << fBit.to_ulong();

  fBit.Print();
} // end member function Print

// Print the many-body state in bit mode
void TAMBSD::PrintInBit() const{
  fBit.PrintInBit();
} // end member function PrintInBit
